/*     */ package com.zimbra.cs.zimlet;
/*     */ 
/*     */ import com.yahoo.platform.yui.compressor.CssCompressor;
/*     */ import com.yahoo.platform.yui.compressor.JavaScriptCompressor;
/*     */ import com.zimbra.common.util.ByteUtil;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.servlet.DiskCacheServlet;
/*     */ import java.io.BufferedReader;
/*     */ import java.io.File;
/*     */ import java.io.IOException;
/*     */ import java.io.InputStreamReader;
/*     */ import java.io.PrintWriter;
/*     */ import java.io.StringReader;
/*     */ import java.io.StringWriter;
/*     */ import java.util.HashMap;
/*     */ import java.util.Iterator;
/*     */ import java.util.Locale;
/*     */ import java.util.Map;
/*     */ import java.util.Set;
/*     */ import java.util.regex.Matcher;
/*     */ import java.util.regex.Pattern;
/*     */ import javax.activation.MimetypesFileTypeMap;
/*     */ import javax.servlet.RequestDispatcher;
/*     */ import javax.servlet.ServletConfig;
/*     */ import javax.servlet.ServletContext;
/*     */ import javax.servlet.ServletException;
/*     */ import javax.servlet.ServletOutputStream;
/*     */ import javax.servlet.ServletRequest;
/*     */ import javax.servlet.ServletResponse;
/*     */ import javax.servlet.WriteListener;
/*     */ import javax.servlet.http.HttpServletRequest;
/*     */ import javax.servlet.http.HttpServletRequestWrapper;
/*     */ import javax.servlet.http.HttpServletResponse;
/*     */ import javax.servlet.http.HttpServletResponseWrapper;
/*     */ import org.mozilla.javascript.ErrorReporter;
/*     */ import org.mozilla.javascript.EvaluatorException;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class ZimletResources
/*     */   extends DiskCacheServlet
/*     */ {
/*     */   private static final String COMPRESSED_EXT = ".zgz";
/*     */   private static final String RESOURCE_PATH = "/res/";
/*     */   private static final String P_DEBUG = "debug";
/*     */   private static final String T_CSS = "css";
/*     */   private static final String T_JAVASCRIPT = "javascript";
/*     */   private static final String T_PLAIN = "plain";
/*  72 */   private static final Map<String, String> TYPES = new HashMap();
/*     */   
/*  74 */   private static final Pattern RE_REMOTE = Pattern.compile("^((https?|ftps?)://|/)");
/*  75 */   private static final Pattern RE_CSS_URL = Pattern.compile("(url\\(['\"]?)([^'\"\\)]*)", 2);
/*     */   
/*  77 */   private boolean supportsGzip = true;
/*     */   
/*     */   static {
/*  80 */     TYPES.put("css", "text/css");
/*  81 */     TYPES.put("js", "text/javascript");
/*  82 */     TYPES.put("xsl", "application/xslt+xml");
/*  83 */     TYPES.put("plain", "text/plain");
/*     */   }
/*     */   
/*     */   public ZimletResources() {
/*  87 */     super("zimletres");
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */   public void init(ServletConfig config)
/*     */     throws ServletException
/*     */   {
/*  96 */     super.init(config);
/*  97 */     String val = getServletConfig().getInitParameter("shouldSupportGzip");
/*  98 */     if (val != null) {
/*  99 */       this.supportsGzip = Boolean.valueOf(val).booleanValue();
/*     */     } else {
/* 101 */       this.supportsGzip = true;
/*     */     }
/*     */   }
/*     */   
/*     */   public void service(ServletRequest request, ServletResponse response)
/*     */     throws IOException, ServletException
/*     */   {
/* 108 */     if (flushCache(request)) {
/* 109 */       return;
/*     */     }
/*     */     
/* 112 */     ZimbraLog.clearContext();
/*     */     
/* 114 */     HttpServletRequest req = (HttpServletRequest)request;
/* 115 */     HttpServletResponse resp = (HttpServletResponse)response;
/*     */     
/* 117 */     String uri = req.getRequestURI();
/* 118 */     String pathInfo = req.getPathInfo();
/*     */     
/* 120 */     if (pathInfo == null) {
/* 121 */       resp.setStatus(400);
/* 122 */       return;
/*     */     }
/*     */     
/*     */ 
/* 126 */     Set<String> zimletNames = (Set)req.getAttribute("com.zimbra.cs.zimlet.Allowed");
/* 127 */     Set<String> allZimletNames = (Set)req.getAttribute("com.zimbra.cs.zimlet.All");
/*     */     
/* 129 */     if (!pathInfo.startsWith("/res/"))
/*     */     {
/* 131 */       ServletContext targetContext = getServletConfig().getServletContext().getContext("/zimlet");
/* 132 */       if (targetContext == null) {
/* 133 */         throw new ServletException("Could not forward the request to zimlet webapp, possible misconfiguration.");
/*     */       }
/* 135 */       RequestDispatcher dispatcher = targetContext.getRequestDispatcher(pathInfo);
/* 136 */       dispatcher.forward(req, resp);
/* 137 */       return;
/*     */     }
/*     */     
/* 140 */     String contentType = getContentType(uri);
/* 141 */     String type = contentType.replaceAll("^.*/", "");
/* 142 */     boolean debug = req.getParameter("debug") != null;
/* 143 */     boolean compress = (!debug) && (this.supportsGzip) && (uri.endsWith(".zgz"));
/*     */     
/* 145 */     String cacheId = getCacheId(req, type, zimletNames, allZimletNames);
/*     */     
/* 147 */     if (ZimbraLog.zimlet.isDebugEnabled()) {
/* 148 */       ZimbraLog.zimlet.debug("DEBUG: uri=" + uri);
/* 149 */       ZimbraLog.zimlet.debug("DEBUG: cacheId=" + cacheId);
/* 150 */       ZimbraLog.zimlet.debug("DEBUG: contentType=" + contentType);
/* 151 */       ZimbraLog.zimlet.debug("DEBUG: type=" + type);
/*     */     }
/*     */     
/*     */ 
/* 155 */     File file = !debug ? getCacheFile(cacheId) : null;
/* 156 */     String text = null;
/*     */     
/* 158 */     if ((file == null) || (!file.exists())) {
/* 159 */       StringWriter writer = new StringWriter();
/* 160 */       PrintWriter printer = new PrintWriter(writer);
/*     */       
/*     */       RequestDispatcher dispatcher;
/* 163 */       if (type.equals("javascript")) {
/* 164 */         ServletConfig config = getServletConfig();
/* 165 */         ServletContext baseContext = config.getServletContext();
/* 166 */         dispatcher = baseContext.getRequestDispatcher("/res/");
/*     */         
/*     */ 
/*     */ 
/*     */ 
/* 171 */         for (String zimletName : allZimletNames) {
/* 172 */           RequestWrapper wrappedReq = new RequestWrapper(req, "/res/" + zimletName);
/* 173 */           ResponseWrapper wrappedResp = new ResponseWrapper(resp, printer);
/* 174 */           wrappedReq.setParameter("debug", "1");
/* 175 */           dispatcher.include(wrappedReq, wrappedResp);
/*     */         }
/*     */       }
/*     */       
/*     */ 
/* 180 */       if (ZimbraLog.zimlet.isDebugEnabled()) {
/* 181 */         ZimbraLog.zimlet.debug("DEBUG: generating buffer");
/*     */       }
/* 183 */       generate(zimletNames, type, printer);
/* 184 */       text = writer.toString();
/*     */       
/*     */ 
/* 187 */       if ((type.equals("css")) && (!debug)) {
/* 188 */         CssCompressor compressor = new CssCompressor(new StringReader(text));
/* 189 */         StringWriter out = new StringWriter();
/* 190 */         compressor.compress(out, 0);
/* 191 */         text = out.toString();
/*     */       }
/*     */       
/* 194 */       if ((type.equals("javascript")) && (!debug))
/*     */       {
/* 196 */         text = text.replaceAll("(^|\n)\\s*DBG\\.\\w+\\(.*\\);\\s*(\n|$)", "\n");
/* 197 */         JavaScriptCompressor compressor = new JavaScriptCompressor(new StringReader(text), new ErrorReporter()
/*     */         {
/*     */ 
/*     */           public void warning(String message, String sourceName, int line, String lineSource, int lineOffset)
/*     */           {
/*     */ 
/* 203 */             if (line < 0) {
/* 204 */               ZimbraLog.zimlet.warn("\n" + message);
/*     */             } else {
/* 206 */               ZimbraLog.zimlet.warn("\n" + line + ':' + lineOffset + ':' + message);
/*     */             }
/*     */           }
/*     */           
/*     */ 
/*     */           public void error(String message, String sourceName, int line, String lineSource, int lineOffset)
/*     */           {
/* 213 */             if (line < 0) {
/* 214 */               ZimbraLog.zimlet.error("\n" + message);
/*     */             } else {
/* 216 */               ZimbraLog.zimlet.error("\n" + line + ':' + lineOffset + ':' + message);
/*     */             }
/*     */           }
/*     */           
/*     */ 
/*     */           public EvaluatorException runtimeError(String message, String sourceName, int line, String lineSource, int lineOffset)
/*     */           {
/* 223 */             error(message, sourceName, line, lineSource, lineOffset);
/* 224 */             return new EvaluatorException(message);
/*     */           }
/* 226 */         });
/* 227 */         StringWriter out = new StringWriter();
/* 228 */         compressor.compress(out, 0, true, false, false, false);
/* 229 */         String mintext = out.toString();
/* 230 */         if (mintext == null) {
/* 231 */           ZimbraLog.zimlet.info("unable to minimize zimlet JS source");
/*     */         } else {
/* 233 */           text = mintext;
/*     */         }
/*     */       }
/*     */       
/*     */ 
/* 238 */       if (!debug)
/*     */       {
/*     */ 
/* 241 */         String uncompressedCacheId = compress ? cacheId.substring(0, cacheId.length() - ".zgz".length()) : cacheId;
/*     */         
/*     */ 
/*     */ 
/* 245 */         file = createCacheFile(uncompressedCacheId, type);
/* 246 */         if (ZimbraLog.zimlet.isDebugEnabled()) {
/* 247 */           ZimbraLog.zimlet.debug("DEBUG: buffer file: " + file);
/*     */         }
/* 249 */         copy(text, file);
/* 250 */         putCacheFile(uncompressedCacheId, file);
/*     */         
/*     */ 
/* 253 */         if (compress) {
/* 254 */           String compressedCacheId = cacheId;
/* 255 */           File gzfile = createCacheFile(compressedCacheId, type + ".gz");
/* 256 */           if (ZimbraLog.zimlet.isDebugEnabled()) {
/* 257 */             ZimbraLog.zimlet.debug("DEBUG: buffer file: " + gzfile);
/*     */           }
/* 259 */           file = compress(file, gzfile);
/* 260 */           putCacheFile(compressedCacheId, file);
/*     */         }
/*     */       }
/*     */     }
/* 264 */     else if (ZimbraLog.zimlet.isDebugEnabled()) {
/* 265 */       ZimbraLog.zimlet.debug("DEBUG: using previous buffer");
/*     */     }
/*     */     
/*     */ 
/*     */ 
/*     */     try
/*     */     {
/* 272 */       resp.addHeader("Vary", "User-Agent");
/* 273 */       if ((file == null) || (req.getProtocol().endsWith("1.0")))
/*     */       {
/*     */ 
/* 276 */         resp.setHeader("Expires", "Tue, 24 Jan 2000 17:46:50 GMT");
/*     */         
/* 278 */         resp.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0");
/*     */         
/* 280 */         resp.setHeader("Pragma", "no-cache");
/*     */       }
/*     */       else
/*     */       {
/* 284 */         resp.setHeader("Cache-Control", "must-revalidate, max-age=0");
/* 285 */         if (file.lastModified() <= req.getDateHeader("If-Modified-Since")) {
/* 286 */           resp.setStatus(304);
/* 287 */           return;
/*     */         }
/* 289 */         resp.setDateHeader("Last-Modified", file.lastModified());
/*     */       }
/* 291 */       resp.setContentType(contentType);
/*     */       
/* 293 */       if ((compress) && (file != null)) {
/* 294 */         resp.setHeader("Content-Encoding", "gzip");
/*     */       }
/*     */       
/*     */ 
/*     */ 
/*     */ 
/* 300 */       if ((!compress) || (file != null)) {
/* 301 */         resp.setContentLength(file != null ? (int)file.length() : text.getBytes("UTF-8").length);
/*     */       }
/*     */     }
/*     */     catch (IllegalStateException e) {
/* 305 */       ZimbraLog.zimlet.debug("zimletres: " + cacheId);
/* 306 */       ZimbraLog.zimlet.debug("zimletres: " + e.getMessage());
/*     */     }
/* 308 */     if (file != null)
/*     */     {
/*     */ 
/*     */ 
/* 312 */       copy(file, resp, false);
/*     */     } else {
/* 314 */       copy(text, resp, compress);
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/* 323 */   private static MimetypesFileTypeMap sFileTypeMap = new MimetypesFileTypeMap();
/*     */   
/*     */   private void printFile(HttpServletResponse resp, String zimletName, String file)
/*     */     throws IOException, ZimletException
/*     */   {
/* 328 */     ZimletFile zf = ZimletUtil.getZimlet(zimletName);
/* 329 */     if (zf == null) {
/* 330 */       ZimbraLog.zimlet.warn("zimlet file not found for: %s", new Object[] { zimletName });
/* 331 */       resp.setStatus(404);
/* 332 */       return;
/*     */     }
/* 334 */     ZimletFile.ZimletEntry entry = zf.getEntry(file);
/* 335 */     if (entry == null) {
/* 336 */       ZimbraLog.zimlet.warn("requested file not found for zimlet: %s (%s)", new Object[] { zimletName, file });
/*     */       
/* 338 */       resp.setStatus(404);
/* 339 */       return;
/*     */     }
/* 341 */     resp.setStatus(200);
/* 342 */     resp.setHeader("Expires", "Tue, 24 Jan 2000 17:46:50 GMT");
/* 343 */     resp.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0");
/* 344 */     resp.setHeader("Pragma", "no-cache");
/* 345 */     String contentType = null;
/* 346 */     int dot = file.lastIndexOf('.');
/* 347 */     if (dot > 0) {
/* 348 */       contentType = (String)TYPES.get(file.substring(dot + 1));
/*     */     }
/* 350 */     if (contentType == null) {
/* 351 */       contentType = sFileTypeMap.getContentType(file);
/*     */     }
/* 353 */     ZimbraLog.zimlet.debug("%s: %s", new Object[] { file, contentType });
/* 354 */     if (contentType != null) {
/* 355 */       resp.setContentType(contentType);
/*     */     }
/* 357 */     ByteUtil.copy(entry.getContentStream(), true, resp.getOutputStream(), false);
/*     */   }
/*     */   
/*     */   private void generate(Set<String> zimletNames, String type, PrintWriter out) throws IOException
/*     */   {
/* 362 */     boolean isCSS = type.equals("css");
/* 363 */     String commentStart = "/* ";
/* 364 */     String commentContinue = " * ";
/* 365 */     String commentEnd = " */";
/*     */     
/*     */ 
/* 368 */     for (String zimlet : zimletNames) {
/* 369 */       ZimletFile file = ZimletUtil.getZimlet(zimlet);
/* 370 */       if (file == null) {
/* 371 */         ZimbraLog.zimlet.warn("error loading " + zimlet + ": zimlet not found ");
/*     */       }
/*     */       else {
/*     */         try
/*     */         {
/* 376 */           String[] files = isCSS ? file.getZimletDescription().getStyleSheets() : file.getZimletDescription().getScripts();
/*     */           
/* 378 */           for (String f : files)
/*     */           {
/* 380 */             if (!RE_REMOTE.matcher(f).matches())
/*     */             {
/*     */ 
/* 383 */               ZimletFile.ZimletEntry entry = file.getEntry(f);
/* 384 */               if (entry != null)
/*     */               {
/*     */ 
/*     */ 
/* 388 */                 out.println(commentStart);
/* 389 */                 out.print(commentContinue);
/* 390 */                 out.print("Zimlet: " + zimlet + "File: " + f);
/* 391 */                 out.println(commentEnd);
/* 392 */                 out.println();
/*     */                 
/* 394 */                 printFile(out, new BufferedReader(new InputStreamReader(entry.getContentStream())), zimlet, isCSS);
/*     */                 
/* 396 */                 out.println();
/*     */               }
/*     */             } }
/* 399 */         } catch (ZimletException e) { ZimbraLog.zimlet.error("error loading " + zimlet + ": ", e);
/*     */         }
/*     */       }
/*     */     }
/* 403 */     out.flush();
/*     */   }
/*     */   
/*     */   private void printFile(PrintWriter out, BufferedReader in, String zimletName, boolean isCSS)
/*     */     throws IOException
/*     */   {
/*     */     String line;
/* 410 */     while ((line = in.readLine()) != null) {
/* 411 */       if (isCSS) {
/* 412 */         Matcher url = RE_CSS_URL.matcher(line);
/* 413 */         if (url.find()) {
/* 414 */           int offset = 0;
/*     */           do {
/* 416 */             int start = url.start();
/* 417 */             if (start > offset) {
/* 418 */               out.print(line.substring(offset, start));
/*     */             }
/* 420 */             out.print(url.group(1));
/*     */             
/* 422 */             String s = url.group(2);
/* 423 */             Matcher remote = RE_REMOTE.matcher(s);
/*     */             
/* 425 */             if (!remote.find()) {
/* 426 */               out.print("/service/zimlet/" + zimletName + "/");
/*     */             }
/*     */             
/* 429 */             out.print(s);
/* 430 */             offset = url.end();
/* 431 */           } while (url.find());
/* 432 */           if (offset >= line.length()) continue;
/* 433 */           out.println(line.substring(offset)); continue;
/*     */         }
/*     */       }
/*     */       
/*     */ 
/* 438 */       out.println(line);
/*     */     }
/* 440 */     in.close();
/*     */   }
/*     */   
/*     */   private static String getContentType(String uri) {
/* 444 */     int index = uri.indexOf('.');
/* 445 */     String type = "plain";
/* 446 */     if (index != -1) {
/* 447 */       type = uri.substring(index + 1);
/* 448 */       index = type.indexOf('.');
/* 449 */       if (index != -1) {
/* 450 */         type = type.substring(0, index);
/*     */       }
/*     */     }
/* 453 */     String contentType = (String)TYPES.get(type);
/* 454 */     return contentType != null ? contentType : (String)TYPES.get("plain");
/*     */   }
/*     */   
/*     */   private String getCacheId(HttpServletRequest req, String type, Set<String> zimletNames, Set<String> allZimletNames)
/*     */   {
/* 459 */     StringBuilder str = new StringBuilder();
/*     */     
/* 461 */     str.append(getLocale(req).toString());
/* 462 */     str.append(":");
/* 463 */     append(str, zimletNames);
/* 464 */     str.append(":");
/* 465 */     append(str, allZimletNames);
/* 466 */     str.append(":");
/* 467 */     str.append(type);
/*     */     
/* 469 */     if (req.getRequestURI().endsWith(".zgz")) {
/* 470 */       str.append(".zgz");
/*     */     }
/* 472 */     return str.toString();
/*     */   }
/*     */   
/*     */   private static void append(StringBuilder dest, Set<String> set) {
/* 476 */     Iterator<String> iter = set.iterator();
/* 477 */     for (int i = 0; iter.hasNext(); i++) {
/* 478 */       if (i > 0) {
/* 479 */         dest.append(",");
/*     */       }
/* 481 */       dest.append((String)iter.next());
/*     */     }
/*     */   }
/*     */   
/*     */   private static Locale getLocale(HttpServletRequest req) {
/* 486 */     String language = req.getParameter("language");
/* 487 */     if (language != null) {
/* 488 */       String country = req.getParameter("country");
/* 489 */       if (country != null) {
/* 490 */         String variant = req.getParameter("variant");
/* 491 */         if (variant != null) {
/* 492 */           return new Locale(language, country, variant);
/*     */         }
/* 494 */         return new Locale(language, country);
/*     */       }
/* 496 */       return new Locale(language);
/*     */     }
/* 498 */     return req.getLocale();
/*     */   }
/*     */   
/*     */ 
/*     */   static class RequestWrapper
/*     */     extends HttpServletRequestWrapper
/*     */   {
/*     */     private String filename;
/*     */     private Map<String, String> parameters;
/*     */     
/*     */     public RequestWrapper(HttpServletRequest req, String filename)
/*     */     {
/* 510 */       super();
/* 511 */       this.filename = filename;
/*     */     }
/*     */     
/*     */     public String getRequestURI()
/*     */     {
/* 516 */       return this.filename + ".js";
/*     */     }
/*     */     
/*     */     public void setParameter(String name, String value) {
/* 520 */       if (this.parameters == null) {
/* 521 */         this.parameters = new HashMap();
/*     */       }
/* 523 */       this.parameters.put(name, value);
/*     */     }
/*     */     
/*     */     public String getParameter(String name) {
/* 527 */       String value = this.parameters != null ? (String)this.parameters.get(name) : null;
/* 528 */       return value == null ? super.getParameter(name) : value;
/*     */     }
/*     */   }
/*     */   
/*     */   static class ResponseWrapper extends HttpServletResponseWrapper {
/*     */     private PrintWriter out;
/*     */     
/*     */     public ResponseWrapper(HttpServletResponse resp, PrintWriter out) {
/* 536 */       super();
/* 537 */       this.out = out;
/*     */     }
/*     */     
/*     */ 
/*     */     public void setHeader(String name, String value) {}
/*     */     
/*     */     public void addHeader(String name, String value) {}
/*     */     
/*     */     public ServletOutputStream getOutputStream()
/*     */       throws IOException
/*     */     {
/* 548 */       return new ZimletResources.ServletStream(getWriter());
/*     */     }
/*     */     
/*     */     public PrintWriter getWriter() throws IOException
/*     */     {
/* 553 */       return this.out;
/*     */     }
/*     */   }
/*     */   
/*     */   static class ServletStream extends ServletOutputStream {
/*     */     private PrintWriter out;
/*     */     
/*     */     public ServletStream(PrintWriter out) {
/* 561 */       this.out = out;
/*     */     }
/*     */     
/*     */     public void write(int i) throws IOException
/*     */     {
/* 566 */       this.out.write(i);
/*     */     }
/*     */     
/*     */     public void write(byte[] b, int off, int len) throws IOException
/*     */     {
/* 571 */       this.out.print(new String(b, off, len, "UTF-8"));
/*     */     }
/*     */     
/*     */     public void print(boolean b) throws IOException
/*     */     {
/* 576 */       this.out.print(b);
/*     */     }
/*     */     
/*     */     public void print(char c) throws IOException
/*     */     {
/* 581 */       this.out.print(c);
/*     */     }
/*     */     
/*     */     public void print(float f) throws IOException
/*     */     {
/* 586 */       this.out.print(f);
/*     */     }
/*     */     
/*     */     public void print(int i) throws IOException
/*     */     {
/* 591 */       this.out.print(i);
/*     */     }
/*     */     
/*     */     public void print(long l) throws IOException
/*     */     {
/* 596 */       this.out.print(l);
/*     */     }
/*     */     
/*     */     public void print(String s) throws IOException
/*     */     {
/* 601 */       this.out.print(s);
/*     */     }
/*     */     
/*     */     public void println() throws IOException
/*     */     {
/* 606 */       this.out.println();
/*     */     }
/*     */     
/*     */     public void println(boolean b) throws IOException
/*     */     {
/* 611 */       this.out.println(b);
/*     */     }
/*     */     
/*     */     public void println(char c) throws IOException
/*     */     {
/* 616 */       this.out.println(c);
/*     */     }
/*     */     
/*     */     public void println(float f) throws IOException
/*     */     {
/* 621 */       this.out.println(f);
/*     */     }
/*     */     
/*     */     public void println(int i) throws IOException
/*     */     {
/* 626 */       this.out.println(i);
/*     */     }
/*     */     
/*     */     public void println(long l) throws IOException
/*     */     {
/* 631 */       this.out.println(l);
/*     */     }
/*     */     
/*     */     public void println(String s) throws IOException
/*     */     {
/* 636 */       this.out.println(s);
/*     */     }
/*     */     
/*     */ 
/*     */     public boolean isReady()
/*     */     {
/* 642 */       return true;
/*     */     }
/*     */     
/*     */     public void setWriteListener(WriteListener listener) {}
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/zimlet/ZimletResources.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */